package com.bfg.controller;

import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Date;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Properties;
import java.util.StringTokenizer;
import java.util.Vector;

public class TestDBConnectionManager {

	static private TestDBConnectionManager instance;
	static private int clients;

	private Vector drivers = new Vector();
	private Hashtable pools = new Hashtable();
	private PrintWriter log;

	public static synchronized TestDBConnectionManager getInstance() {
		if (instance == null)
			instance = new TestDBConnectionManager();
		clients++;
		return instance;
	}

	private TestDBConnectionManager() {
		init();
	}

	public void freeConnection(String name, Connection conn) {
		DbConnectionPool pool = (DbConnectionPool) pools.get(name);
		if (pool != null)
			pool.freeConnection(conn);
	}

	public Connection getConnection(String name) {
		DbConnectionPool pool = (DbConnectionPool) pools.get(name);
		if (pool != null)
			return pool.getConnection();
		return null;
	}

	public Connection getConnection(String name, long time) {
		DbConnectionPool pool = (DbConnectionPool) pools.get(name);
		if (pool != null)
			return pool.getConnection(time);
		return null;
	}

	public synchronized void release() {
		if (--clients != 0)
			return;
		Enumeration allPools = pools.elements();
		while (allPools.hasMoreElements()) {
			DbConnectionPool pool = (DbConnectionPool) allPools.nextElement();
			pool.release();
		}
		Enumeration allDrivers = drivers.elements();
		while (allDrivers.hasMoreElements()) {
			Driver driver = (Driver) allDrivers.nextElement();
			try {
				DriverManager.deregisterDriver(driver);
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}

	private void init() {
		InputStream is = getClass().getResourceAsStream("/db.properties");
		Properties dbProps = new Properties();
		try {
			dbProps.load(is);
		} catch (IOException e) {
			e.printStackTrace();
		}
		String logFile=dbProps.getProperty("logFile","TestDBConnectionManager.log");
		System.out.println(logFile);
		try {
			log=new PrintWriter(new FileWriter(logFile,true),true);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		loadDrivers(dbProps);
		createPools(dbProps);
	}

	private void createPools(Properties dbProps) {
		Enumeration propsName = dbProps.propertyNames();
		while (propsName.hasMoreElements()) {
			String name = (String) propsName.nextElement();
			if (name.endsWith(".url")) {
				String poolName = name.substring(0, name.lastIndexOf("."));
				String url = dbProps.getProperty(poolName + ".url");
				if (url == null) {
					log("no URL specified for " + poolName);
					continue;
				}
				String user = dbProps.getProperty(poolName + ".username");
				String pass = dbProps.getProperty(poolName + ".password");
				String maxConn = dbProps
						.getProperty(poolName + ".maxConn", "0");
				int max;
				try {
					max = Integer.valueOf(maxConn).intValue();
				} catch (NumberFormatException e) {
					max = 0;
				}
				System.out.println("poolName - " + poolName);
				System.out.println("url - " + url);
				System.out.println("username - " + user);
				System.out.println("password - " + pass);
				DbConnectionPool pool = new DbConnectionPool(poolName, url,
						user, pass, max);
				pools.put(poolName, pool);
				pool.settingLogFile(log);
				log("Initialized pool " + poolName);
			}
		}
	}

	private void loadDrivers(Properties dbProps) {
		String driverClass = dbProps.getProperty("driver.mssql");
		StringTokenizer st = new StringTokenizer(driverClass);

		try {
			String driverClassname = st.nextToken().trim();
			System.out.println("loading driver - " + driverClassname);
			Driver driver = (Driver) Class.forName(driverClassname)
					.newInstance();
			drivers.addElement(driver);
			DriverManager.registerDriver(driver);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}
	
	private void log(String message) {
		log.println(new Date()+" : "+message);
	}
	
	private void log(Throwable e, String message) {
		log.println(new Date()+" : "+message);
		e.printStackTrace(log);
	}

}
